package com.apobates.jforum2.troll.accounts;

import com.apobates.jforum2.troll.accounts.biz.MemberActionDescriptor;
import com.apobates.jforum2.troll.accounts.biz.MemberActiveRecordsService;
import com.apobates.jforum2.troll.accounts.biz.impl.api.MemberActionLogStreamProvider;
import com.apobates.jforum2.troll.accounts.entity.Member;
import com.apobates.jforum2.troll.accounts.entity.MemberActiveRecords;
import com.apobates.jforum2.troll.regular.ForumActionEnum;
import com.apobates.jforum2.troll.regular.MemberAction;
import com.apobates.jforum2.troll.regular.event.MemberActionLog;
import com.apobates.jforum2.troll.utils.core.api.IpLocation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

@Configuration
@Aspect
public class MemberActionLogAspect {
    @Autowired
    private MemberActiveRecordsService memberActiveRecordsService;
    @Autowired
    private MemberActionLogStreamProvider memberActionLogStreamProvider;
    private final static Logger logger = LoggerFactory.getLogger(MemberActionLogAspect.class);

    //目前有:MEMBER_PROFILE_AVATAR,MEMBER_PASSPORT,MEMBER_PASSPORT_REST,MEMBER_PROFILE_BASE,MEMBER_REGISTER,MEMBER_LOGIN,MEMBER_LOGOUT
    @AfterReturning(pointcut = "@annotation(memberAction) && args(.., actionDescriptor)", returning = "retVal")
    public void check(
            JoinPoint joinPoint,
            MemberAction memberAction,
            MemberActionDescriptor actionDescriptor,
            Object retVal) throws Throwable {
        //
        Object[] paramValues = joinPoint.getArgs();
        CodeSignature signature = (CodeSignature) joinPoint.getStaticPart().getSignature();
        ForumActionEnum action = memberAction.action();
        String masterArgName = memberAction.keyName();
        Class<?> masterArgType = memberAction.keyType();
        logger.error(String.format("[MAT]arg name: %s, arg Type: %s, action: %s", masterArgName, masterArgType, action.getTitle()));
        // 返回值
        Member data = null;
        boolean status = false;

        if(retVal instanceof Member) {
            data = (Member) retVal;
        } else{
            try {
                Member m = parseMember(signature, paramValues, masterArgType, masterArgName);
                data = m;
            }catch (Exception e){
                if(logger.isDebugEnabled()){
                    logger.debug(e.getMessage(), e);
                }
                data = Member.guestMember();
                logger.error("[MAT]get primary key error: exception:"+e.getMessage());
            }
        }
        if (null != data) { // 执行失败的
            status = true;
        }
        MemberActionLog mal = memberActionLogStreamProvider.action(action, data, actionDescriptor, status);
        try {
            //保存活跃记录
            saveActiveRecords(mal, actionDescriptor);
        }catch (Exception e){
            logger.error("[MAT] save member active record has exception:"+e.getMessage());
        }
    }

    private void saveActiveRecords(MemberActionLog mal, MemberActionDescriptor actionDescriptor){
        MemberActiveRecords mar = new MemberActiveRecords(
                mal.getAction(),
                mal.isSuccess(),
                mal.getMemberId(),
                mal.getMemberNickname(),
                mal.getIpAddr(),
                mal.getRefererURL(),
                mal.getToken(),
                mal.getDevice(),
                actionDescriptor.getAgent());
        IpLocation location = actionDescriptor.location();
        mar.setIsp(location.getIsp());
        mar.setProvince(location.getProvince());
        mar.setDistrict(location.getDistrict());
        mar.setCity(location.getCity());
        mar.setActiveDateTime(mal.getDateTime());
        memberActiveRecordsService.create(mar);
    }

    private Member parseMember(CodeSignature signature, Object[] paramValues, Class<?> masterArgType, String masterArgName){
        Long memberId = 0L;
        String names = Member.GUEST_NAMES;
        //
        String[] methodArguNames = signature.getParameterNames();
        for (int i = 0; i < paramValues.length; i++) {
            logger.error(String.format("[MAT]method arg name: %s, method param Value: %s", methodArguNames[i], paramValues[i]));
            if (masterArgName.equals(methodArguNames[i])) {
                if (masterArgType == Long.class) {
                    memberId = (Long) paramValues[i];
                } else if (masterArgType == String.class) {
                    names = (String) paramValues[i];
                }
            }
        }
        if (memberId > 0 && Member.GUEST_NAMES.equals(names)) {
            //取到names
            names = "*";
        }
        Member m = new Member();
        m.setId(memberId);
        m.setNickname(names);
        return m;
    }
}
